package com.xx.happychatboot.middleware.jwt.service.impl;

import com.xx.happychatboot.base.constant.RedisConstant;
import com.xx.happychatboot.middleware.jwt.service.JwtService;
import com.xx.happychatboot.base.utils.JwtTokenUtils;
import com.xx.happychatboot.base.utils.RedisUtils;
import com.xx.happychatboot.middleware.springsecurity.domain.vo.response.AuthResponse;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Service
public class JwtServiceImpl implements JwtService {

    @Autowired
    private JwtTokenUtils jwtTokenUtils;

    @Override
    public AuthResponse refreshToken(String refreshToken) {
        try {
            // 校验 Token 是否可用, 若解析异常，针对不同异常做出不同的响应参数
            jwtTokenUtils.validateToken(refreshToken);
        } catch (SignatureException | MalformedJwtException | UnsupportedJwtException | IllegalArgumentException e) {
            return AuthResponse.authFail("无效的Token");
        } catch (ExpiredJwtException e) {
            return AuthResponse.authFail("Token已过期");
        } catch (Exception e) {
            return AuthResponse.authFail("Token校验异常");
        }

        String username = jwtTokenUtils.getUsernameByToken(refreshToken);

        Long expire = RedisUtils.getExpire(RedisConstant.JWT_REFRESH + username);

        String redisToken = RedisUtils.getStr(RedisConstant.JWT_REFRESH + username);

        if (StringUtils.isBlank(redisToken)) {
            return AuthResponse.authFail("Token已过期");
        }

        if (!redisToken.equals(refreshToken)) {
            return AuthResponse.authFail("Token校验异常");
        }

        // 刷新token与redis的token一致，且未过期，则刷新新的token
        if (Objects.nonNull(expire)) {
            String newAccessToken = jwtTokenUtils.generateToken(username);
            String newRefreshToken = jwtTokenUtils.generateRefreshToken(username);
            RedisUtils.set(RedisConstant.JWT_ACCESS + username, newAccessToken, RedisConstant.TOKEN_EXPIRE_DAYS, TimeUnit.HOURS);
            RedisUtils.set(RedisConstant.JWT_REFRESH + username, newRefreshToken, RedisConstant.TOKEN_EXPIRE_DAYS * 2, TimeUnit.HOURS);
            return new AuthResponse(200, "刷新token成功", newAccessToken, newRefreshToken);
        }

        return AuthResponse.authFail("刷新Token失败");
    }
}
